home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / Other Langs / Tickle-4.0 (tcl) / tcl / expecTerm / scrinfo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-17  |  13.4 KB  |  412 lines  |  [TEXT/MPS ]

  1. /* scrinfo.c - access information about screen contents and attributes
  2. ***************************************************************************** 
  3. expecTerm version 1.0 beta
  4. Mark Weissman
  5. Christopher Matheus
  6. Copyright 1992 by GTE Laboratories Incorporated.
  7.  
  8. Portions of this work are in the public domain.  Permission to use,
  9. copy, modify, and distribute this software and its documentation for
  10. any purpose and without fee is hereby granted, provided that the above
  11. copyright notice appear in all copies and that both the copyright
  12. notice and warranty disclaimer appear in supporting documentation, and
  13. that the names of GTE Laboratories or any of their entities not be
  14. used in advertising or publicity pertaining to distribution of the
  15. software without specific, written prior permission.
  16.  
  17. GTE disclaims all warranties with regard to this software, including
  18. all implied warranties of merchantability and fitness for a particular
  19. purpose, even if GTE Laboratories Incorporated knows about the
  20. purpose.  In no event shall GTE be liable for any special, indirect or
  21. consequential damages or any damages whatsoever resulting from loss of
  22. use, data or profits, whether in an action of contract, negligence or
  23. other tortuous action, arising out of or in connection with the use or
  24. performance of this software.
  25.  
  26. This code is based on and may include parts of Don Libes' expect code:
  27.   expect written by: Don Libes, NIST, 2/6/90
  28.   Design and implementation of expect was paid for by U.S. tax
  29.   dollars.  Therefore it is public domain.  However, the author and NIST
  30.   would appreciate credit if this program or parts of it are used.
  31. ******************************************************************************
  32.  
  33. Written by: Chris Matheus  May1992 
  34.             Mark Weissman
  35. */
  36.  
  37. #include <stdio.h>
  38. #include <ctype.h>
  39. #include <tcl.h>
  40. #include "win.h"
  41. #include "global.h"
  42. #include "scrinfo.h"
  43.  
  44. void printsr(sr)
  45. ScreenRegion *sr;
  46.   printf("         screen region: r:%d %d c:%d %d r_r:%d %d r_c:%d %d rrp:%c rcp:%c, casep: %c\n",
  47.       sr->rowmin,sr->rowmax,sr->colmin, sr->colmax,
  48.       sr->relrowmin,sr->relrowmax,sr->relcolmin, sr->relcolmax,
  49.       sr->relrowp, sr->relcolp, sr->casep);
  50. }
  51.  
  52. char *ScreenDumpContents(minrow,maxrow,mincol,maxcol,
  53.               scr_attr_flag, non_print_char, casep)
  54. int maxrow, maxcol, minrow, mincol;
  55. char scr_attr_flag;
  56. char non_print_char;
  57. char casep;
  58. {
  59.     int col, row;
  60.     static char dumpbuf[XMAX*YMAX], *bufp;
  61.     extern char charyx();
  62.     extern char attryx();
  63.  
  64.     /* printf("%d %d %d %d %d\n",minrow,maxrow,mincol,maxcol,scr_attr_flag); */
  65.   
  66.     bufp = dumpbuf;
  67.     if (scr_attr_flag == SCR_ATTRIBUTES) { /* scr_attr_flag: -1 -> attr, 1 -> contents */
  68.     for (row = minrow; row <= maxrow; row++) {
  69.         for (col = mincol; col <= maxcol; col++)
  70.         *bufp++ = (charyx(row,col)) ? attryx(row,col) :  '_';
  71.         if (row < maxrow) *bufp++ = '\n';
  72.     }
  73.     } 
  74.     else if (scr_attr_flag == SCR_CONTENTS) {
  75.     for (row = minrow; row <= maxrow; row++) {
  76.         for (col = mincol; col <= maxcol; col++) {
  77.         *bufp = charyx(row,col);
  78.         if (!*bufp) *bufp = ' ';
  79.         else if (non_print_char && !isprint(*bufp)) /* check */
  80.             *bufp = non_print_char;
  81.         else if ((casep == SCR_IGNORE) && *bufp >= 'A' && *bufp <= 'Z')
  82.             *bufp += ('a'-'A');
  83.         bufp++;
  84.         }
  85.         if (row < maxrow) *bufp++ = '\n';
  86.     }
  87.     }
  88.     *bufp = '\0';
  89.     return(dumpbuf);
  90. }
  91.  
  92. /* get contents or attributes for specified screen_region */
  93. char *get_screen_region(sr)
  94. ScreenRegion *sr;
  95. {
  96.   int rowmin, rowmax, colmin, colmax;
  97.   long Cols = Session->columns;
  98.   long Rows = Session->rows;
  99.     
  100.   if (sr->relrowp == SCR_RELATIVE) {
  101.       rowmin = (sr->relrowmin + Session->y);
  102.       if (rowmin < sr->rowmin) {                /* check within clip region */
  103.       rowmin = sr->rowmin;          
  104.       } else if (rowmin > (Rows - 1)) { /* check within screen */
  105.       rowmin = (Rows - 1);   
  106.       }
  107.       rowmax = (sr->relrowmax + Session->y);
  108.       if (rowmax > sr->rowmax) {                 /* check within clip region */
  109.       rowmax = sr->rowmax;          
  110.       } else if (rowmax > (Rows - 1)) { /* check within screen */
  111.       rowmax = (Rows - 1);   
  112.       }
  113.       
  114.   } else {
  115.       rowmin = sr->rowmin;
  116.       rowmax = sr->rowmax;
  117.   }
  118.  
  119.   if (sr->relcolp == SCR_RELATIVE) {
  120.       colmin = (sr->relcolmin + Session->x);
  121.       if (colmin < sr->colmin) {                 /* check within clip region */
  122.       colmin = sr->colmin;          
  123.       } else if (colmin > (Cols - 1)) { /* check within screen */
  124.       colmin = (Cols - 1);   
  125.       }
  126.  
  127.       colmax = (sr->relcolmax + Session->x);
  128.       if (colmax > sr->colmax) {             /* check within clip region */
  129.       colmax = sr->colmax;          
  130.       } else if (colmax > (Cols - 1)) { /* check within screen */
  131.       colmax = (Cols - 1);   
  132.       }
  133.       
  134.   } else {
  135.       colmin = sr->colmin;
  136.       colmax = sr->colmax;
  137.   }
  138.  
  139.  
  140.   return ScreenDumpContents(rowmin, rowmax, colmin, colmax, sr->match_type, sr->non_print_char, sr->casep);
  141. }
  142.  
  143.  
  144. void
  145. init_screen_region(sr)
  146. ScreenRegion *sr;
  147. {
  148.   char *v;
  149.   
  150.   if ((v = get_var(CLIP_ROWMIN_VAR)) > (char *)0) sr->rowmin = atoi(v);
  151.   else sr->rowmin = 0;
  152.   if ((v = get_var(CLIP_ROWMAX_VAR)) > (char *)0) sr->rowmax = atoi(v);
  153.   else if (Session) sr->rowmax = (Session->rows - 1);
  154.   if ((v = get_var(CLIP_COLMIN_VAR)) > (char *)0) sr->colmin = atoi(v);
  155.   else sr->colmin = 0;
  156.   if ((v = get_var(CLIP_COLMAX_VAR)) > (char *)0) sr->colmax = atoi(v);
  157.   else if (Session) sr->colmax = (Session->columns - 1);
  158.  
  159.   sr->relrowmin = REL_ROWMIN_DEFAULT;
  160.   sr->relrowmax = REL_ROWMAX_DEFAULT;
  161.   sr->relcolmin = REL_COLMIN_DEFAULT;
  162.   sr->relcolmax = REL_COLMAX_DEFAULT;
  163.   sr->relrowp = SCR_ABSOLUTE;
  164.   sr->relcolp = SCR_ABSOLUTE;
  165.   sr->match_type = SCR_SERIAL;
  166.   sr->non_print_char = SCR_DEFAULT_NON_PRINT_CHAR;
  167.   sr->casep = SCR_NORMAL;
  168.   sr->breaksp = SCR_BREAKS;
  169. }
  170.  
  171. /*ARGSUSED*/
  172. int
  173. cmdScreenInfo(clientData, interp, argc, argv)
  174. ClientData clientData;
  175. Tcl_Interp *interp;
  176. int argc;
  177. char **argv;
  178. {
  179.   int m = -1;            /* master process file descriptor */
  180.   int i, screen_argp = 0; 
  181.   int previous_results = 0;
  182.   char temp_buf[128];
  183.   ScreenRegion sr_struct, *sr = &sr_struct;
  184.   
  185.   for (i=1;i<argc;i++) {
  186.     if (streq(argv[i],"-i")) {
  187.       if (argc == ++i) goto usage_error;
  188.       m = atoi(argv[i]);
  189.       break;
  190.     }
  191.   }
  192.   if ((m == -1) && (update_master(&m) == 0)) return(TCL_ERROR);
  193.  
  194.   if (!SetSessionFromFD(m)) {
  195.     tcl_error("spawn_id %d not associated with a terminal emulator.", m);
  196.     return TCL_ERROR;
  197.   }
  198.   
  199.   if (argc > 1) init_screen_region(sr);
  200.  
  201.   for (i=1;i<argc;i++) {
  202.     if (streq(argv[i],"-i")) {
  203.       ++i; continue;
  204.     } else if (streq(argv[i],"-numrows")) {
  205.       previous_results = 1;
  206.       sprintf(temp_buf,"%d",Session->rows);
  207.       Tcl_AppendElement(interp, temp_buf, 0);
  208.     } else if (streq(argv[i],"-numcols") || streq(argv[i],"-numcolumns")) {
  209.       previous_results = 1;
  210.       sprintf(temp_buf,"%d",Session->columns);
  211.       Tcl_AppendElement(interp, temp_buf, 0);
  212.     } else if (streq(argv[i],"-cursor_row")) {
  213.       previous_results = 1;
  214.       sprintf(temp_buf,"%d",Session->y);
  215.       Tcl_AppendElement(interp, temp_buf, 0);
  216.     } else if (streq(argv[i],"-cursor_col") || (streq(argv[i],"-cursor_column"))) {
  217.       previous_results = 1;
  218.       sprintf(temp_buf,"%d",Session->x);
  219.       Tcl_AppendElement(interp, temp_buf, 0);
  220.     } else if (streq(argv[i],"-info")) {
  221.       sprintf(interp->result,
  222.           "rows=%d:%d\ncols=%d:%d\nrrows=%d:%d\nrcols=%d:%d\nrelrowp=%s\nrelcolp=%s\nmatch_type=%s\nCase=%s\n",
  223.           sr->rowmin,sr->rowmax,sr->colmin, sr->colmax,
  224.           sr->relrowmin,sr->relrowmax,sr->relcolmin, sr->relcolmax,
  225.           ((sr->relrowp==SCR_RELATIVE)?"True":"False"), 
  226.           ((sr->relcolp==SCR_RELATIVE)?"True":"False"),
  227.           ((sr->match_type==SCR_ATTRIBUTES)?"Attributes":
  228.            (sr->match_type==SCR_CONTENTS)?"Contents":
  229.            (sr->match_type==SCR_SERIAL)?"Serial":
  230.            "*Unknown*"),
  231.           ((sr->casep == SCR_IGNORE)?"Ignore":"Normal")
  232.           );
  233.       return TCL_OK; 
  234.     } else if (parse_screen_argument(argc, argv, &i, sr)) {
  235.       if (i == -1) return TCL_ERROR;
  236.       screen_argp = 1;
  237.     } else if (streq(argv[i],"-nocase")) {
  238.       sr->match_type = SCR_CONTENTS;
  239.       screen_argp = 1;
  240.     } else goto usage_error;
  241.   }
  242.   if (screen_argp) {
  243.     if (previous_results) Tcl_AppendElement(interp, get_screen_region(sr), TCL_STATIC);
  244.     else Tcl_SetResult(interp, get_screen_region(sr), TCL_STATIC);
  245.   }
  246.   else if (!previous_results) {
  247.     Tcl_SetResult(interp, 
  248.           ScreenDumpContents(0,(Session->rows - 1),0, (Session->columns - 1), 
  249.                      SCR_CONTENTS,0,SCR_NORMAL), 
  250.           TCL_STATIC);
  251.   }
  252.   return TCL_OK;
  253.   
  254.  usage_error:
  255.   tcl_error("usage: %s [-i spawn_id] [-nocase] [-numrows] [-numcols] [-cursor_row] [-cursor_col] [screen region]", argv[0]);
  256.   return TCL_ERROR;
  257.   
  258. }
  259.  
  260. int
  261. parse_screen_argument(argc, argv, i, sr)
  262. int argc, *i;
  263. char **argv;
  264. ScreenRegion *sr;
  265. {
  266.   int min, max;
  267.   extern double atof();
  268.  
  269.   if (streq(argv[*i],"-screen") || streq(argv[*i],"-scr")) {
  270.       sr->match_type = SCR_CONTENTS;
  271.   } else if ((streq(argv[*i],"-attr")) || (streq(argv[*i],"-attributes"))) {
  272.       sr->match_type = SCR_ATTRIBUTES;
  273.   } else if (streq(argv[*i],"-serial")) {
  274.     sr->match_type = SCR_SERIAL;
  275.   } else if (streq(argv[*i],"-nocase")) {
  276.     sr->casep = SCR_IGNORE;
  277.     return(0);    /* return 0 so expect can reuse -nocase flag */
  278.   } else if (streq(argv[*i],"-nobreaks")) {
  279.     if (sr->match_type == SCR_SERIAL) sr->match_type = SCR_CONTENTS;
  280.     sr->breaksp = SCR_NOBREAKS;
  281.   } else if (streq(argv[*i],"-breaks")) {
  282.     if (sr->match_type == SCR_SERIAL) sr->match_type = SCR_CONTENTS;
  283.     sr->breaksp = SCR_BREAKS;
  284.   } else if (streq(argv[*i],"-breaks")) {
  285.     if (sr->match_type == SCR_SERIAL) sr->match_type = SCR_CONTENTS;
  286.     sr->breaksp = SCR_BREAKS;
  287.   } else if (streq(argv[*i],"-cols") || streq(argv[*i],"-columns") || 
  288.          streq(argv[*i],"-clipcol") || streq(argv[*i],"-clipcolumn")) {
  289.     if (parse_min_max((*i+1==argc), argv[*i+1], &min, &max,
  290.               -(Session->columns-1), (Session->columns-1))
  291.     == TCL_ERROR) goto number_error;
  292.     ++(*i);
  293.     if (sr->match_type == SCR_SERIAL) sr->match_type = SCR_CONTENTS;
  294.     if (min < 0) min = min + Session->columns;
  295.     if (max < 0) max = max + Session->columns;
  296.     if (sr->colmin < min) sr->colmin = min;
  297.     if (sr->colmax > max) sr->colmax = max;
  298.   } else if (streq(argv[*i],"-rows") || streq(argv[*i],"-cliprow")) {
  299.     if (parse_min_max((*i+1==argc), argv[*i+1], &min, &max, -(Session->rows - 1), (Session->rows - 1))
  300.     == TCL_ERROR) goto number_error;
  301.     ++(*i);
  302.     if (sr->match_type == SCR_SERIAL) sr->match_type = SCR_CONTENTS;
  303.     if (min < 0) min = min + Session->rows;
  304.     if (max < 0) max = max + Session->rows;
  305.     if (sr->rowmin < min) sr->rowmin = min;
  306.     if (sr->rowmax > max) sr->rowmax = max;
  307.   } else if (streq(argv[*i],"-rcols") || streq(argv[*i],"-rcolumns")) {
  308.     if (parse_min_max((*i+1==argc), argv[*i+1], &min, &max, -(Session->columns - 1), (Session->columns - 1))
  309.     == TCL_ERROR) goto number_error;
  310.     ++(*i);
  311.     if (sr->match_type == SCR_SERIAL) sr->match_type = SCR_CONTENTS;
  312.     sr->relcolmin += min;
  313.     sr->relcolmax += max;
  314.     sr->relcolp = SCR_RELATIVE;
  315.   } else if (streq(argv[*i],"-rrows")) {
  316.     if (parse_min_max((*i+1==argc), argv[*i+1], &min, &max, -(Session->rows - 1), (Session->rows - 1))
  317.     == TCL_ERROR) goto number_error;
  318.     ++(*i);
  319.     if (sr->match_type == SCR_SERIAL) sr->match_type = SCR_CONTENTS;
  320.     sr->relrowmin += min;
  321.     sr->relrowmax += max;
  322.     sr->relrowp = SCR_RELATIVE;
  323.   } else if (streq(argv[*i],"-nonprint")) {
  324.     if ((*i+1) == argc) goto usage_error;
  325.     ++(*i);
  326.     sr->match_type = SCR_CONTENTS;
  327.     sr->non_print_char = argv[*i][0];
  328.   } else return 0;        /* argv[*i] is not a screen argument */
  329.   
  330.   return 1;        /* argv[*i] is a screen argument; return new index */
  331.   
  332.  usage_error:
  333.   tcl_error("error parsing %s argument: %s", argv[0], argv[*i]);
  334.   return (*i = -1);
  335.  
  336.  number_error:
  337.   tcl_error("badly formed number or range for %s: %s", argv[*i-1], argv[*i]);
  338.   return (*i = -1);
  339. }
  340.  
  341. int parse_min_max(argc_error, argument, min, max, absmin, absmax)
  342. char *argument;
  343. int argc_error, *min, *max;
  344. {
  345.     char argbuf[128], *arg;
  346.     char *minptr, *maxptr;
  347.     
  348.     if (argc_error) return TCL_ERROR;
  349.  
  350.     strcpy(argbuf, argument);
  351.     minptr = maxptr = arg = argbuf;
  352.     for (;*arg;arg++) {
  353.     if (*arg == ':') {
  354.         *arg = '\0';
  355.         maxptr = arg+1;
  356.     } else if (!(*arg == '$' || *arg == '^' || *arg == '-' || isdigit(*arg)))
  357.         return TCL_ERROR;
  358.     }
  359.  
  360.     *min = my_atoi(minptr, absmin, absmax);
  361.     if (*min < absmin) *min = absmin;
  362.     *max = my_atoi(maxptr, absmin, absmax);
  363.     if (*max > absmax) *max = absmax;
  364.  
  365.     return TCL_OK;
  366. }
  367.  
  368. int my_atoi(n, absmin, absmax)
  369. char *n;
  370. int absmin, absmax;
  371. {
  372.    if (*n == '$') return absmax;
  373.    if (*n == '^') return absmin;
  374.    return atoi(n);
  375. }
  376.  
  377. void
  378. init_scr_region_variables()
  379. {
  380.   Tcl_SetVar(interp,CLIP_ROWMIN_VAR,"-1",0);
  381.   Tcl_SetVar(interp,CLIP_ROWMAX_VAR,"-1",0);
  382.   Tcl_SetVar(interp,CLIP_COLMIN_VAR,"-1",0);
  383.   Tcl_SetVar(interp,CLIP_COLMAX_VAR,"-1",0);
  384. }
  385.  
  386.  
  387. int get_start_row(sr, start)
  388. ScreenRegion *sr;
  389. int start;
  390. {
  391.   int row, cols, result=0;
  392.   if (sr->relrowp == 'r') row = Session->y + sr->relrowmin;
  393.   else row = sr->rowmin;
  394.   if (sr->relcolp == 'r') cols = sr->relcolmax - sr->relcolmin;
  395.   else cols = sr->colmax - sr->colmin + 2;
  396.   if (cols) result = (row + (start / cols));
  397.   return(result);
  398. }
  399.  
  400. int get_start_col(sr, start)
  401. ScreenRegion *sr;
  402. int start;
  403. { int col, cols;
  404.   if (sr->relcolp == 'r') col = Session->x + sr->relcolmin;
  405.   else col = sr->colmin;
  406.   if (sr->relcolp == 'r') cols = sr->relcolmax - sr->relcolmin;
  407.   else cols = sr->colmax - sr->colmin + 2;
  408.   if (cols) return (col + (start % cols));
  409.   else return 0;
  410. }
  411.